Skip to content

Feat/cart type diagnostic#44

Open
mrtwebdesign wants to merge 2 commits into
developmentfrom
feat/cart-type-diagnostic
Open

Feat/cart type diagnostic#44
mrtwebdesign wants to merge 2 commits into
developmentfrom
feat/cart-type-diagnostic

Conversation

@mrtwebdesign

Copy link
Copy Markdown
Contributor

Added logging to help capture source of a cart-crashing error.

mrtwebdesign and others added 2 commits July 2, 2026 12:04
…ure (v1.2.0)

Opt-in via HYPERCART_CART_TYPE_DIAGNOSTIC (plus a
hypercart_cart_type_diagnostic_enabled filter override) to find the root
cause of the cart/checkout fatal "TypeError: Unsupported operand types:
float / string" in WC_Discounts::sort_by_price()
(universal-child-theme issue #888).

Two error-level events:

- cart_type_corruption: snapshot cart item quantity/price/discounted_price
  at woocommerce_before_calculate_totals priority PHP_INT_MIN, re-check at
  PHP_INT_MAX. Reports each non-numeric value with type-safe rendering
  (objects/arrays never string-cast), origin attribution
  (upstream / hook_callback / added_during_hook), applied coupons, user id,
  request context, and callback lists for the six hooks able to write cart
  item values.
- cart_fatal_captured: register_shutdown_function catcher that matches the
  TypeError itself and dumps per-item quantity/price types from the
  in-memory cart. Covers paths that never fire the totals hook —
  WC_Cart::apply_coupon() validates via new WC_Discounts(WC()->cart)
  before any totals calculation.

Safety: all entry points swallow Throwable so the tracer can never take
down the cart it observes; re-entrancy guard on the snapshot; log volume
capped at 5 events per PHP process with signature de-duplication across
repeat hook firings.

In WC 10.8.x only a non-numeric string quantity can raise this fatal
(price is float-cast in WC_Discounts and WC_Cart_Totals), so quantity
findings are the authoritative signal.

Verified end to end on the Local site with a temporary corrupting
mu-plugin: hook-window capture attributed the culprit by file and line
({closure@zz-cart-diag-corruptor-TEMP.php:12}), and the shutdown catcher
captured a real resulting fatal (float * string in USPS weight-based
shipping) with a full cart type dump. 142 PHPUnit tests pass (19 new in
tests/CartDiagTest.php).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three items from the second-session code review of the cart type
diagnostic:

- Document the usage constraint (file header + README): the corruption
  scan runs on every woocommerce_before_calculate_totals firing even on
  clean carts, adding one filtered get_price() read per cart item per
  totals calculation — enable to reproduce, then disable; not a
  permanent fixture.
- Comment the edit/view context mix on price rows (check pass) and note
  in the README that corrupted_by on price rows is a hint, not proof —
  quantity rows carry the authoritative signal.
- Make cart_diag_capture_fatal() self-guarded: public entry point now
  wraps a private body in try/catch like the other diagnostic entry
  points, so it never throws regardless of caller; docblock notes it is
  public for testability.

No behavior change to detection or attribution. 142 tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mrtwebdesign mrtwebdesign changed the base branch from main to development July 8, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant